﻿using System.Drawing;

namespace System.NETool;

public static class Drawing
{
    /// <summary>
    /// 判断p1,p2的连线是否与q1,q2的连线相交
    /// https://www.cnblogs.com/tuyang1129/p/9390376.html
    /// </summary>
    /// <param name="p1">p1,p2的连线第一个点</param>
    /// <param name="p2">p1,p2的连线第二个点</param>
    /// <param name="q1">q1,q2的连线第一个点</param>
    /// <param name="q2">q1,q2的连线第二个点</param>
    /// <returns>是否相交</returns>
    public static bool IsIntersect(Point p1, Point p2, Point q1, Point q2)
    {
        //排斥试验，判断p1p2在q1q2为对角线的矩形区之外
        //P1P2中最大的X比Q1Q2中的最小X还要小，说明P1P2在Q1Q2的最左点的左侧，不可能相交。
        if (Math.Max(p1.X, p2.X) < Math.Min(q1.X, q2.X))
        {
            return false;
        }

        //P1P2中最小的X比Q1Q2中的最大X还要大，说明P1P2在Q1Q2的最右点的右侧，不可能相交。
        if (Math.Min(p1.X, p2.X) > Math.Max(q1.X, q2.X))
        {
            return false;
        }

        //P1P2中最大的Y比Q1Q2中的最小Y还要小，说明P1P2在Q1Q2的最低点的下方，不可能相交。
        if (Math.Max(p1.Y, p2.Y) < Math.Min(q1.Y, q2.Y))
        {
            return false;
        }

        //P1P2中最小的Y比Q1Q2中的最大Y还要大，说明P1P2在Q1Q2的最高点的上方，不可能相交。
        if (Math.Min(p1.Y, p2.Y) > Math.Max(q1.Y, q2.Y))
        {
            return false;
        }

        //计算第一条的两个端点 
        double num1 = Compute(p1.X - p2.X, p1.Y - p2.Y, p1.X - q1.X, p1.Y - q1.Y);
        //在第二条线段的两边 
        double num2 = Compute(p1.X - p2.X, p1.Y - p2.Y, p1.X - q2.X, p1.Y - q2.Y);
        //计算第二条的两个端点 
        double num3 = Compute(p1.X - q1.X, p1.Y - q1.Y, q1.X - q2.X, q1.Y - q2.Y);
        //在第一条线段的两边 
        double num4 = Compute(p2.X - q1.X, p2.Y - q1.Y, q1.X - q2.X, q1.Y - q2.Y);

        //等于0表示成180度角
        return num1 * num2 < 0 && num3 * num4 <= 0 || num1 * num2 <= 0 && num3 * num4 < 0;
    }

    /// <summary>
    /// 计算叉乘的结果
    /// </summary>
    /// <param name="x1">第一个向量的X分量</param>
    /// <param name="y1">第一个向量的Y分量</param>
    /// <param name="x2">第二个向量的X分量</param>
    /// <param name="y2">第二个向量的Y分量</param>
    /// <returns>叉乘的结果</returns>
    internal static double Compute(double x1, double y1, double x2, double y2)
    {
        return x1 * y2 - y1 * x2;
    }

    /// <summary>
    /// 计算两条直线的交点
    /// </summary>
    /// <param name="lineFirstStar">L1的点1 坐标</param>
    /// <param name="lineFirstEnd">L1的点2 坐标</param>
    /// <param name="lineSecondStar">L2的点1 坐标</param>
    /// <param name="lineSecondEnd">L2的点2 坐标</param>
    /// <param name="intersection">交点</param>
    /// <returns>是否有交点</returns>
    public static bool GetIntersection(PointF lineFirstStar, PointF lineFirstEnd, PointF lineSecondStar, PointF lineSecondEnd, out PointF intersection)
    {
        intersection = new PointF(0, 0);

        /*
         * L1，L2都存在斜率的情况：
         * 直线方程L1: ( y - y1 ) / ( y2 - y1 ) = ( x - x1 ) / ( x2 - x1 )
         * => y = [ ( y2 - y1 ) / ( x2 - x1 ) ]( x - x1 ) + y1
         * 令 a = ( y2 - y1 ) / ( x2 - x1 )
         * 有 y = a * x - a * x1 + y1   .........1
         * 直线方程L2: ( y - y3 ) / ( y4 - y3 ) = ( x - x3 ) / ( x4 - x3 )
         * 令 b = ( y4 - y3 ) / ( x4 - x3 )
         * 有 y = b * x - b * x3 + y3 ..........2
         *
         * 如果 a = b，则两直线平等，否则， 联解方程 1,2，得:
         * x = ( a * x1 - b * x3 - y1 + y3 ) / ( a - b )
         * y = a * x - a * x1 + y1
         *
         * L1存在斜率, L2平行Y轴的情况：
         * x = x3
         * y = a * x3 - a * x1 + y1
         *
         * L1 平行Y轴，L2存在斜率的情况：
         * x = x1
         * y = b * x - b * x3 + y3
         *
         * L1与L2都平行Y轴的情况：
         * 如果 x1 = x3，那么L1与L2重合，否则平等
         *
         */

        float a = 0, b = 0;
        int state = 0;
        if (lineFirstStar.X.NotEquals(lineFirstEnd.X))
        {
            a = (lineFirstEnd.Y - lineFirstStar.Y) / (lineFirstEnd.X - lineFirstStar.X);
            state |= 1;
        }

        if (lineSecondStar.X.NotEquals(lineSecondEnd.X))
        {
            b = (lineSecondEnd.Y - lineSecondStar.Y) / (lineSecondEnd.X - lineSecondStar.X);
            state |= 2;
        }

        switch (state)
        {
            case 0: //L1与L2都平行Y轴
                {
                    if (lineFirstStar.X.EqualsFloat(lineSecondStar.X))
                    {
                        //throw new Exception("两条直线互相重合，且平行于Y轴，无法计算交点。");
                        return false;
                    }
                    else
                    {
                        //throw new Exception("两条直线互相平行，且平行于Y轴，无法计算交点。");
                        return false;
                    }
                }
            case 1: //L1存在斜率, L2平行Y轴
                {
                    float x = lineSecondStar.X;
                    float y = (lineFirstStar.X - x) * (-a) + lineFirstStar.Y;
                    intersection = new PointF(x, y);
                    return true;
                }
            case 2: //L1 平行Y轴，L2存在斜率
                {
                    float x = lineFirstStar.X;
                    //网上有相似代码的，这一处是错误的。你可以对比case 1 的逻辑 进行分析
                    //源code:lineSecondStar * x + lineSecondStar * lineSecondStar.X + p3.Y;
                    float y = (lineSecondStar.X - x) * (-b) + lineSecondStar.Y;
                    intersection = new PointF(x, y);
                    return true;
                }
            case 3: //L1，L2都存在斜率
                {
                    if (a.EqualsFloat(b))
                    {
                        // throw new Exception("两条直线平行或重合，无法计算交点。");
                        return false;
                    }

                    float x = (a * lineFirstStar.X - b * lineSecondStar.X - lineFirstStar.Y + lineSecondStar.Y) / (a - b);
                    float y = a * x - a * lineFirstStar.X + lineFirstStar.Y;
                    intersection = new PointF(x, y);
                    return true;
                }
            default:
                {
                    return false;
                }
        }
    }

    /// <summary>
    /// 计算方位角和距离得到的点
    /// </summary>
    /// <param name="this">中心点</param>
    /// <param name="range">距离</param>
    /// <param name="az">方位角</param>
    /// <param name="xOffset">X轴偏移量</param>
    /// <param name="yOffset">Y轴偏移量</param>
    /// <returns>计算得到的点</returns>
    public static PointF CalcAzRangePoint(this PointF @this, float range, float az, float xOffset = 0, float yOffset = 0)
    {
        float x = (float)(range * 1.0f * Math.Sin(az * Math.PI / 180));
        float y = (float)(range * 1.0f * Math.Cos(az * Math.PI / 180));
        return new PointF(@this.X + xOffset + x, @this.Y + yOffset - y);
    }

    /// <summary>
    /// 计算方位角和距离得到的点
    /// </summary>
    /// <param name="this">中心点</param>
    /// <param name="range">距离</param>
    /// <param name="az">方位角</param>
    /// <param name="xOffset">X轴偏移量</param>
    /// <param name="yOffset">Y轴偏移量</param>
    /// <returns>计算得到的点</returns>
    public static PointF CalcAzRangePoint(this Point @this, float range, float az, float xOffset = 0, float yOffset = 0)
    {
        float x = (float)(range * 1.0f * Math.Sin(az * Math.PI / 180));
        float y = (float)(range * 1.0f * Math.Cos(az * Math.PI / 180));
        return new PointF(@this.X + xOffset + x, @this.Y + yOffset - y);
    }

    /// <summary>
    /// 计算两点之间的距离
    /// </summary>
    /// <param name="this">第一个点</param>
    /// <param name="pt2">第二个点</param>
    /// <returns>两点之间的距离</returns>
    public static double CalcDistance(this PointF @this, PointF pt2)
    {
        float xx = @this.X - pt2.X;
        float yy = @this.Y - pt2.Y;
        return Math.Sqrt(xx * xx + yy * yy);
    }

    /// <summary>
    /// 计算两点之间的距离
    /// </summary>
    /// <param name="this">第一个点</param>
    /// <param name="pt2">第二个点</param>
    /// <returns>两点之间的距离</returns>
    public static double CalcDistance(this Point @this, Point pt2)
    {
        int xx = @this.X - pt2.X;
        int yy = @this.Y - pt2.Y;
        return Math.Sqrt(xx * xx + yy * yy);
    }

    /// <summary>
    /// 计算两点之间的方位角
    /// </summary>
    /// <param name="this">起始点</param>
    /// <param name="toPoint">目标点</param>
    /// <returns>两点之间的方位角</returns>
    public static double CalcAngle(this Point @this, Point toPoint)
    {
        double az = Math.Atan2(@this.Y - toPoint.Y, @this.X - toPoint.X) * 180 / Math.PI;
        az = (az - 270 + 720) % 360;
        return az;
    }

    /// <summary>
    /// 计算两点之间的方位角
    /// </summary>
    /// <param name="this">起始点</param>
    /// <param name="toPoint">目标点</param>
    /// <returns>两点之间的方位角</returns>
    public static double CalcAngle(this PointF @this, PointF toPoint)
    {
        double az = Math.Atan2(@this.Y - toPoint.Y, @this.X - toPoint.X) * 180 / Math.PI;
        az = (az - 270 + 720) % 360;
        return az;
    }

    /// <summary>
    /// 计算矩形的中心点
    /// </summary>
    /// <param name="this">矩形</param>
    /// <returns>矩形的中心点</returns>
    public static PointF Center(this Rectangle @this)
    {
        return new PointF(@this.Left + @this.Width / 2.0f, @this.Top + @this.Height / 2.0f);
    }

    /// <summary>
    /// 计算矩形的中心点
    /// </summary>
    /// <param name="this">矩形</param>
    /// <returns>矩形的中心点</returns>
    public static PointF Center(this RectangleF @this)
    {
        return new PointF(@this.Left + @this.Width / 2.0f, @this.Top + @this.Height / 2.0f);
    }

    /// <summary>
    /// 设置颜色的透明度
    /// </summary>
    /// <param name="this">颜色</param>
    /// <param name="alpha">透明度</param>
    /// <returns>设置透明度后的颜色</returns>
    public static Color Alpha(this Color @this, byte alpha)
    {
        return Color.FromArgb(alpha, @this);
    }

    /// <summary>
    /// 判断点是否在矩形内
    /// </summary>
    /// <param name="this">点</param>
    /// <param name="rect">矩形</param>
    /// <returns>是否在矩形内</returns>
    public static bool InRect(this Point @this, Rectangle rect)
    {
        return @this.X >= rect.Left && @this.X <= rect.Right && @this.Y >= rect.Top && @this.Y <= rect.Bottom;
    }

    /// <summary>
    /// 判断点是否在矩形内
    /// </summary>
    /// <param name="this">点</param>
    /// <param name="rect">矩形</param>
    /// <returns>是否在矩形内</returns>
    public static bool InRect(this Point @this, RectangleF rect)
    {
        return @this.X >= rect.Left && @this.X <= rect.Right && @this.Y >= rect.Top && @this.Y <= rect.Bottom;
    }

    /// <summary>
    /// 判断点是否在矩形内
    /// </summary>
    /// <param name="this">点</param>
    /// <param name="rect">矩形</param>
    /// <returns>是否在矩形内</returns>
    public static bool InRect(this PointF @this, Rectangle rect)
    {
        return @this.X >= rect.Left && @this.X <= rect.Right && @this.Y >= rect.Top && @this.Y <= rect.Bottom;
    }

    /// <summary>
    /// 判断点是否在矩形内
    /// </summary>
    /// <param name="this">点</param>
    /// <param name="rect">矩形</param>
    /// <returns>是否在矩形内</returns>
    public static bool InRect(this PointF @this, RectangleF rect)
    {
        return @this.X >= rect.Left && @this.X <= rect.Right && @this.Y >= rect.Top && @this.Y <= rect.Bottom;
    }

    /// <summary>
    /// 两个矩阵是否重叠（边沿重叠，也认为是重叠）
    /// </summary>
    /// <param name="this">第一个矩阵的位置</param>
    /// <param name="rc2">第二个矩阵的位置</param>
    /// <returns></returns>
    public static bool IsOverlap(this Rectangle @this, Rectangle rc2)
    {
        return @this.X + @this.Width > rc2.X &&
               rc2.X + rc2.Width > @this.X &&
               @this.Y + @this.Height > rc2.Y &&
               rc2.Y + rc2.Height > @this.Y;
    }


    /// <summary>
    /// 两个矩阵是否重叠（边沿重叠，也认为是重叠）
    /// </summary>
    /// <param name="this">第一个矩阵的位置</param>
    /// <param name="rc2">第二个矩阵的位置</param>
    /// <returns></returns>
    public static bool IsOverlap(this RectangleF @this, RectangleF rc2)
    {
        return @this.X + @this.Width > rc2.X &&
               rc2.X + rc2.Width > @this.X &&
               @this.Y + @this.Height > rc2.Y &&
               rc2.Y + rc2.Height > @this.Y;
    }

    /// <summary>
    /// 两点创建一个矩形
    /// </summary>
    /// <param name="this">点1</param>
    /// <param name="pf2">点2</param>
    /// <returns>矩形</returns>
    public static RectangleF CreateRectangleF(this PointF @this, PointF pf2)
    {
        return new RectangleF(Math.Min(@this.X, pf2.X), Math.Min(@this.Y, pf2.Y),
            Math.Abs(@this.X - pf2.X), Math.Abs(@this.Y - pf2.Y));
    }

    /// <summary>
    /// 两点创建一个矩形
    /// </summary>
    /// <param name="this">点1</param>
    /// <param name="pf2">点2</param>
    /// <returns>矩形</returns>
    public static Rectangle CreateRectangle(this Point @this, Point pf2)
    {
        return new Rectangle(Math.Min(@this.X, pf2.X), Math.Min(@this.Y, pf2.Y),
            Math.Abs(@this.X - pf2.X), Math.Abs(@this.Y - pf2.Y));
    }

    /// <summary>
    /// 计算直线在给定X坐标处的Y坐标
    /// </summary>
    /// <param name="this">直线的第一个点</param>
    /// <param name="pf2">直线的第二个点</param>
    /// <param name="x">给定的X坐标</param>
    /// <returns>对应的Y坐标</returns>
    public static double CalcY(this PointF @this, PointF pf2, double x)
    {
        if (@this.Y.Equals(pf2.Y)) return @this.Y;
        if (@this.X.Equals(pf2.X)) return float.NaN;

        double a = (pf2.Y - @this.Y) * 1.0 / (pf2.X - @this.X);
        double b = @this.Y - a * @this.X;
        return a * x + b;
    }

    /// <summary>
    /// 计算直线在给定Y坐标处的X坐标
    /// </summary>
    /// <param name="this">直线的第一个点</param>
    /// <param name="pf2">直线的第二个点</param>
    /// <param name="y">给定的Y坐标</param>
    /// <returns>对应的X坐标</returns>
    public static double CalcX(this PointF @this, PointF pf2, double y)
    {
        if (@this.X.Equals(pf2.X)) return @this.X;
        if (@this.Y.Equals(pf2.Y)) return float.NaN;

        double a = (pf2.Y - @this.Y) * 1.0 / (pf2.X - @this.X);
        double b = @this.Y - a * @this.X;
        return (y - b) * 1.0 / a;
    }

    /// <summary>
    /// 计算直线在给定X坐标处的Y坐标
    /// </summary>
    /// <param name="this">直线的第一个点</param>
    /// <param name="pf2">直线的第二个点</param>
    /// <param name="x">给定的X坐标</param>
    /// <returns>对应的Y坐标</returns>
    public static double CalcY(this Point @this, Point pf2, double x)
    {
        if (@this.Y == pf2.Y) return @this.Y;
        if (@this.X == pf2.X) return double.NaN;

        double a = (pf2.Y - @this.Y) * 1.0 / (pf2.X - @this.X);
        double b = @this.Y - a * @this.X;
        return a * x + b;
    }

    /// <summary>
    /// 计算直线在给定Y坐标处的X坐标
    /// </summary>
    /// <param name="this">直线的第一个点</param>
    /// <param name="pf2">直线的第二个点</param>
    /// <param name="y">给定的Y坐标</param>
    /// <returns>对应的X坐标</returns>
    public static double CalcX(this Point @this, Point pf2, double y)
    {
        if (@this.Y == pf2.Y) return @this.X;
        if (@this.X == pf2.X) return double.NaN;

        double a = (pf2.Y - @this.Y) * 1.0 / (pf2.X - @this.X);
        double b = @this.Y - a * @this.X;
        return (y - b) * 1.0 / a;
    }

    /// <summary>
    /// 设置递进颜色
    /// </summary>
    /// <param name="this">颜色</param>
    /// <param name="alpha">alpha</param>
    /// <returns>颜色</returns>
    public static Color StepColor(this Color @this, byte alpha)
    {
        if (alpha == 100)
        {
            return @this;
        }

        byte a = @this.A;
        byte r = @this.R;
        byte g = @this.G;
        byte b = @this.B;
        float bg;

        double d = (alpha - 100.0) / 100.0;

        if (d > 100)
        {
            // blend with white
            bg = 255.0F;
            d = 1.0F - d; // 0 = transparent fg; 1 = opaque fg
        }
        else
        {
            // blend with black
            bg = 0.0F;
            d = 1.0F + d; // 0 = transparent fg; 1 = opaque fg
        }

        r = (byte)(BlendColor(r, bg, d));
        g = (byte)(BlendColor(g, bg, d));
        b = (byte)(BlendColor(b, bg, d));

        return Color.FromArgb(a, r, g, b);
    }

    /// <summary>
    /// 混合颜色
    /// </summary>
    /// <param name="fg">前景色</param>
    /// <param name="bg">背景色</param>
    /// <param name="alpha">透明度</param>
    /// <returns>混合后的颜色</returns>
    private static double BlendColor(double fg, double bg, double alpha)
    {
        double result = bg + alpha * (fg - bg);
        if (result < 0.0)
        {
            result = 0.0;
        }

        if (result > 255)
        {
            result = 255;
        }

        return result;
    }

    /// <summary>
    /// 判断颜色是否为空或透明
    /// </summary>
    /// <param name="this">颜色</param>
    /// <returns>是否为空或透明</returns>
    public static bool IsNullOrEmpty(this Color @this)
    {
        return @this == Color.Empty || @this == Color.Transparent;
    }

    /// <summary>
    /// 判断颜色是否有效
    /// </summary>
    /// <param name="this">颜色</param>
    /// <returns>是否有效</returns>
    public static bool IsValid(this Color @this)
    {
        return !@this.IsNullOrEmpty();
    }

    /// <summary>
    /// 平移
    /// </summary>
    /// <param name="this">点</param>
    /// <param name="size">大小</param>
    /// <returns>平移后的点</returns>
    public static Point Offset(this Point @this, Size size)
    {
        @this.Offset(size.Width, size.Height);
        return @this;
    }

    /// <summary>
    /// 宽度放大
    /// </summary>
    /// <param name="this">大小</param>
    /// <param name="multiple">倍数</param>
    /// <returns>放大后的大小</returns>
    public static Size MultiplyWidth(this Size @this, int multiple)
    {
        return @this with { Width = @this.Width * multiple };
    }

    /// <summary>
    /// 高度放大
    /// </summary>
    /// <param name="this">大小</param>
    /// <param name="multiple">倍数</param>
    /// <returns>放大后的大小</returns>
    public static Size MultiplyHeight(this Size @this, int multiple)
    {
        return @this with { Height = @this.Height * multiple };
    }

    /// <summary>
    /// 宽度和高度放大
    /// </summary>
    /// <param name="this">大小</param>
    /// <param name="multiple">倍数</param>
    /// <returns>放大后的大小</returns>
    public static Size MultiplyAll(this Size @this, int multiple)
    {
        return new Size(@this.Width * multiple, @this.Height * multiple);
    }

    /// <summary>
    /// 宽度放大
    /// </summary>
    /// <param name="this">大小</param>
    /// <param name="multiple">倍数</param>
    /// <returns>放大后的大小</returns>
    public static Size MultiplyWidth(this Size @this, double multiple)
    {
        return @this with { Width = (int)(@this.Width * multiple) };
    }

    /// <summary>
    /// 高度放大
    /// </summary>
    /// <param name="this">大小</param>
    /// <param name="multiple">倍数</param>
    /// <returns>放大后的大小</returns>
    public static Size MultiplyHeight(this Size @this, double multiple)
    {
        return @this with { Height = (int)(@this.Height * multiple) };
    }

    /// <summary>
    /// 宽度和高度放大
    /// </summary>
    /// <param name="this">大小</param>
    /// <param name="multiple">倍数</param>
    /// <returns>放大后的大小</returns>
    public static Size MultiplyAll(this Size @this, double multiple)
    {
        return new Size((int)(@this.Width * multiple), (int)(@this.Height * multiple));
    }

    /// <summary>
    /// 区域是否可见
    /// </summary>
    /// <param name="this">矩形</param>
    /// <returns>是否可见</returns>
    public static bool IsVisible(this Rectangle @this)
    {
        return @this is { Width: > 0, Height: > 0 };
    }

    /// <summary>
    /// 生成随机颜色
    /// </summary>
    /// <returns>随机颜色</returns>
    public static Color RandomColor()
    {
        var random = new Random(DateTime.Now.Microsecond);
        return Color.FromArgb(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256));
    }

    /// <summary>
    /// 颜色是否是浅色
    /// </summary>
    /// <param name="this">颜色</param>
    /// <returns>是否是浅色</returns>
    public static bool IsLightColor(this Color @this)
    {
        return (0.299 * @this.R + 0.587 * @this.G + 0.114 * @this.B) / 255 > 0.5;
    }

    /// <summary>
    /// 根据背景色判断前景色
    /// </summary>
    /// <param name="backColor">背景色</param>
    /// <returns>前景色</returns>
    public static Color ForeColor(Color backColor)
    {
        return backColor.IsLightColor() ? Color.Black : Color.White;
    }

    /// <summary>
    /// SizeF转Size
    /// </summary>
    /// <param name="this">SizeF</param>
    /// <returns>Size</returns>
    public static Size Size(this SizeF @this)
    {
        return new Size(@this.Width.RoundEx(), @this.Height.RoundEx());
    }

    /// <summary>
    /// PointF转Point
    /// </summary>
    /// <param name="this">PointF</param>
    /// <returns>Point</returns>
    public static Point Point(this PointF @this)
    {
        return new Point(@this.X.RoundEx(), @this.Y.RoundEx());
    }

    /// <summary>
    /// Size增加长宽
    /// </summary>
    /// <param name="this">Size</param>
    /// <param name="width">宽</param>
    /// <param name="height">长</param>
    /// <returns>结果</returns>
    public static Size Add(this Size @this, int width, int height)
    {
        return new Size(@this.Width + width, @this.Height + height);
    }

    /// <summary>
    /// SizeF增加长宽
    /// </summary>
    /// <param name="this">SizeF</param>
    /// <param name="width">宽</param>
    /// <param name="height">长</param>
    /// <returns>结果</returns>
    public static SizeF Add(this SizeF @this, float width, float height)
    {
        return new SizeF(@this.Width + width, @this.Height + height);
    }

    /// <summary>
    /// Color转HTML
    /// </summary>
    /// <param name="this">Color</param>
    /// <returns>HTML</returns>
    public static string ToHtml(this Color @this)
    {
        return ColorTranslator.ToHtml(@this);
    }

    /// <summary>
    /// HTML转Color
    /// </summary>
    /// <param name="htmlColor">HTML</param>
    /// <param name="alpha">透明度</param>
    /// <returns>Color</returns>
    public static Color ToColor(string htmlColor, byte alpha = 255)
    {
        return Color.FromArgb(alpha, ColorTranslator.FromHtml(htmlColor));
    }
}